package com.ccteam.fluidmusic.ui.moment

import android.app.Application
import android.os.Parcelable
import androidx.lifecycle.*
import com.ccteam.fluidmusic.utils.Event
import com.ccteam.fluidmusic.utils.UploadFileUtils
import com.ccteam.fluidmusic.view.bean.ErrorMessage
import com.ccteam.fluidmusic.view.bean.LoadMessage
import com.ccteam.model.Resource
import com.ccteam.model.moment.MOMENT_SHARE_TYPE_NONE
import com.ccteam.network.ApiError
import com.ccteam.network.exception.ApiException
import com.ccteam.shared.domain.file.UploadImageTokenDataUseCase
import com.ccteam.shared.domain.moment.PublishMomentDataUseCase
import com.ccteam.shared.result.moment.MomentListItem
import com.luck.picture.lib.entity.LocalMedia
import com.orhanobut.logger.Logger
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.*
import kotlinx.parcelize.Parcelize
import javax.inject.Inject
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine

/**
 * @author Xiaoc
 * @since 2021/3/30
 *
 * 发布朋友圈ViewModel
 */
@HiltViewModel
class PublishMomentViewModel @Inject constructor(
    application: Application,
    private val uploadFileUtils: UploadFileUtils,
    private val tokenDataUseCase: UploadImageTokenDataUseCase,
    private val publishMomentDataUseCase: PublishMomentDataUseCase,
    savedStateHandle: SavedStateHandle
): AndroidViewModel(application) {

    private val _loadMessage = MutableLiveData<Event<LoadMessage>>()
    val loadMessage: LiveData<Event<LoadMessage>> get() = _loadMessage

    /**
     * 是否启用发布按钮
     */
    private val _enablePublishMomentButton = MutableLiveData(false)
    val enablePublishMomentButton: LiveData<Boolean> get() = _enablePublishMomentButton

    /**
     * 分享内容的暂存
     */
    private val _shareItem = MutableLiveData<MomentListItem.MomentShareItem?>(null)
    val shareItem: LiveData<MomentListItem.MomentShareItem?> get() = _shareItem

    /**
     * 暂存发布的朋友圈内容，防止进入选择内容界面返回输入内容消失
     */
    val momentContent = StringBuilder()

    /**
     * 设置是否启用发布按钮
     */
    fun setEnablePublishMoment(enable: Boolean){
        _enablePublishMomentButton.value = enable
    }

    fun setMomentContent(content: String){
        momentContent.clear()
        momentContent.append(content)
    }

    /**
     * 设置分享内容
     */
    fun setShareItem(shareItem: MomentListItem.MomentShareItem){
        _shareItem.value = shareItem
    }

    /**
     * 清楚分享内容
     */
    fun clearShareItem(){
        _shareItem.value = null
    }

    /**
     * 发布朋友圈
     */
    fun publishMoment(photoList: List<LocalMedia>){
        val application = getApplication<Application>()

        if(momentContent.toString().isEmpty()){
            _loadMessage.value = Event(LoadMessage.Error(ErrorMessage("朋友圈内容为空",ApiError.unknownCode)))
            return
        }
        val shareType = if(_shareItem.value == null){
            MOMENT_SHARE_TYPE_NONE
        } else {
            _shareItem.value!!.type
        }

        _loadMessage.value = Event(LoadMessage.Loading)

        viewModelScope.launch {

            val token = if(!photoList.isNullOrEmpty()){
                // 获取图片上传需要的Token
                val tokenResult = tokenDataUseCase(null)
                if(tokenResult !is Resource.Success){
                    _loadMessage.value = Event(LoadMessage.Error(ErrorMessage(tokenResult.message,tokenResult.errorCode)))
                    return@launch
                }
                tokenResult.data
            } else {
                null
            }

            val photoUrlList = if(token != null){
                // 如果Token不为空，则上传所需要的图片
                val photoIndexPairList = mutableListOf<Pair<Int,String>>()

                val listJob = photoList.mapIndexed { index, localMedia ->
                    async(Dispatchers.IO) {
                        suspendCoroutine<Nothing?> { cn ->
                            launch {
                                uploadFileUtils.upload(
                                    application,token,
                                    index,localMedia.path,{},
                                    uploadSuccess = { index,fileUrl ->
                                        photoIndexPairList.add(Pair(index,fileUrl))
                                        cn.resume(null)
                                    },{ errorMessage ->
                                        _loadMessage.postValue(Event(LoadMessage.Error(ErrorMessage(errorMessage))))
                                        // 发生错误后直接取消协程不允许进行后续操作
                                        cn.resumeWithException(ApiException(ApiError.serverErrorCode,errorMessage))
                                    }
                                )
                            }
                        }
                    }
                }

                listJob.forEach {
                    it.await()
                }
                // 将上传的图片按索引进行排序
                photoIndexPairList.sortBy {
                    it.first
                }

                // 取消掉上传图片的listJob
                listJob.forEach {
                    it.cancel()
                }
                // 仅保留图片地址的List
                Logger.d("上传图片地址：${photoIndexPairList}")
                photoIndexPairList.map {
                    it.second
                }

            } else {
                emptyList()
            }

            val result = publishMomentDataUseCase(
                PublishMomentDataUseCase.PublishMomentRequest(
                    shareType,momentContent.toString(),_shareItem.value?.id, photoUrlList)
            )

            if(result is Resource.Success){
                _loadMessage.value = Event(LoadMessage.Success)
            } else {
                _loadMessage.value = Event(LoadMessage.Error(ErrorMessage(result.message,result.errorCode)))
            }

        }
    }
}

@Parcelize
data class ShareContentData(
    val shareId: String,
    val shareImgUrl: String,
    val shareTitle: String,
    val type: Int
): Parcelable